package io.gitee.caoxiaoyu97.log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.springframework.aop.support.AopUtils;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.function.Consumer;

/*********************************************************
 * 文件名称：LogAutoProxy.java
 * 系统名称：CXY自定义系统
 * 模块名称：io.gitee.caoxiaoyu97.log
 * 功能说明：
 * 开发人员 @author：caoxy31978
 * 开发时间 @date：2023/7/12 9:05
 * 修改记录：程序版本  修改日期  修改人员  修改单号  修改说明
 *********************************************************/
@Aspect
public class LogAutoProxy {

    @Pointcut("@within(org.springframework.stereotype.Service)")
    public void allService(){}

    @Pointcut("@within(org.springframework.stereotype.Controller)")
    public void allController(){}

    @Pointcut("@within(org.springframework.stereotype.Component)")
    public void allComponent(){}

    @Before("allService() || allController()")
    public void before(JoinPoint joinPoint){
        Consumer<Logger> startLog = (logger)->{
            CxyLoggerUtils.startTransaction(logger);
        };
        controlLifeCycle(joinPoint, startLog);
    }

    private static void controlLifeCycle(JoinPoint joinPoint, Consumer<Logger> doLog) {

        Object aThis = joinPoint.getThis();
        Class<?> targetClass = AopUtils.getTargetClass(aThis);
        if (targetClass != null && targetClass.getName().contains("$$")) {
            targetClass = targetClass.getSuperclass();
        }
        Field[] declaredFields = targetClass.getDeclaredFields();
        for (Field field : declaredFields) {
            Class<?> aClass = field.getType();
            if (aClass == Logger.class){
                field.setAccessible(true);
                try {
                    doLog.accept((Logger) field.get(aThis));
                }catch (Exception e){}
            }
        }
    }

    @After("allService() || allController()")
    public void after(JoinPoint joinPoint){
        Consumer<Logger> startLog = (logger)->{
            CxyLoggerUtils.endTransaction(logger);
        };
        controlLifeCycle(joinPoint, startLog);
    }
}
